#ifndef CCONTRIL_MANAGE_H_
#define CCONTRIL_MANAGE_H_

#include <QDateTime>
#include <QUuid>
#include "CcmdBase.h"
#include "CEntranceHttpClient.h"
#include "CEntranceHttpServer.h"
#include "CEntranceMqttClient.h"
#include "qudpserver.h"
#include "CControlTool.h"
#include "cmdHandle/CNetConfig.h"
#include <functional>
#define NET_MSG_LOG



#include "ControlManage/cmdHandleBase.ih"
#include "ControlManage/cmdHandle.ih"


#define ADD_CONTROL_CMD(cmdStr,cmdFunc, recvData, sendData)  \
controlManage::addControlCmd(cmdStr \
		, std::bind(&cmdFunc, this, _1, _2, _3)\
		, recvData, sendData);

#define ADD_CONTROL_CMD_TYPE(cmdStr,cmdFunc, recvData, sendData, isAppointDataRecv, isAppointDataSend, isAuthorization) \
		controlManage::addControlCmd<decltype(std::bind(&cmdFunc, this, _1, _2, _3)), decltype(recvData), decltype(sendData)>(cmdStr \
				, std::bind(&cmdFunc, this, _1, _2, _3)\
				, recvData, sendData,isAppointDataRecv, isAppointDataSend, isAuthorization);

#define ADD_CONTROL_CMD_TYPE_FUNC(cmdStr,cmdFunc, recvData, sendData, heartbeat, isAppointDataRecv, isAppointDataSend, isAuthorization) \
		controlManage::addControlCmd<decltype(std::bind(&cmdFunc, this, _1, _2, _3)), decltype(recvData), decltype(sendData)>(cmdStr \
				, std::bind(&cmdFunc, this, _1, _2, _3)\
				, recvData, sendData, heartbeat, isAppointDataRecv, isAppointDataSend, isAuthorization);

#define STD_BIND_FUNC(func, ...) std::bind(&func, ## __VA_ARGS__)

NETWORKSERVICE_BEGIN_NAMESPACE

/*
 * handle 管理类
 */
class QTNETWORK_EXPORT controlManage {
private:
	controlManage(){};
public:
	template <class HandleFuncType, class HandleRecvType,class HandleSendType>
	static void addControlCmd(string cmd, HandleFuncType hand,HandleRecvType recv,HandleSendType send, void *userData = NULL){
        cmdHandleBase::m_HanderMap[cmd] = new cmdHandle<HandleFuncType,HandleRecvType,HandleSendType>(hand, userData);
		cmdHandleBase::addCmd(cmd);

	}

	template <class HandleFuncType, class HandleRecvType,class HandleSendType>
	static void addControlCmd(string cmd, HandleFuncType hand,HandleRecvType recv,HandleSendType send, bool isAppointDataRecv, bool isAppointDataSend = false, bool isAuthorization = true, void *userData = NULL){
        cmdHandleBase::m_HanderMap[cmd] = new cmdHandle<HandleFuncType,HandleRecvType,HandleSendType>(hand, recv, send,isAppointDataRecv,isAppointDataSend, isAuthorization, userData);
		cmdHandleBase::addCmd(cmd);
	}

	template <class HandleFuncType, class HandleRecvType,class HandleSendType>
	static void addControlCmd(string cmd, HandleFuncType hand,HandleRecvType recv,HandleSendType send, std::function<void()> &&heartbeat,  bool isAppointDataRecv, bool isAppointDataSend = false, bool isAuthorization = true, void *userData = NULL){
        cmdHandleBase::m_HanderMap[cmd] = new cmdHandle<HandleFuncType,HandleRecvType,HandleSendType>(hand, recv, send,isAppointDataRecv,isAppointDataSend, isAuthorization, userData);
        cmdHandleBase::m_HanderMap[cmd]->setHeartbeatTriggerFunc(heartbeat);
		cmdHandleBase::addCmd(cmd);
	}

	// 添加心跳触发函数
	static void addHeartbeatHandle(string cmd, std::function<void()> &&heartbeat){
        std::map<string, cmdHandleBase*>::iterator itr = cmdHandleBase::m_HanderMap.find(cmd);
        if(itr == cmdHandleBase::m_HanderMap.end()){
			std::function<bool (void*, void*, void*)> tmp;
            cmdHandleBase::m_HanderMap[cmd] = new cmdHandle<decltype(tmp),string,string>(tmp, string(), string(),false,false, false, nullptr);
            cmdHandleBase::m_HanderMap[cmd]->setHeartbeatTriggerFunc(heartbeat);
		} else {
			itr->second->setHeartbeatTriggerFunc(heartbeat);
		}

	}

	// 获取注册接口
    static std::map<string, cmdHandleBase*> &getHanderMap(){ return cmdHandleBase::m_HanderMap; }


    // 本设备作为UDP服务端收到消息
    static bool runUdpHandle(T_CmdBaseData *head, string &data, struct tRoute *route = NULL);

    // 本设备作为http服务端收到消息
    static bool runHttpHandle(struct _tCmdBaseData *head, string &body, struct tRoute *route = NULL);

    // 本设备收到消息mqtt
    static bool runMqttHandle(struct _tCmdBaseData *head, string &body, struct tRoute *route = NULL);


    // 本设备作为HTTP客户端执行请求
    template <class HandleSendType,class HandleRecvType>
    static bool httpRequest(struct tRouteData<HandleSendType> *send,struct tRouteData<HandleRecvType> *recv){
        return cmdHandleBase::httpRequest(send, recv);
    }

	// 本设备作为UDP客户端执行请求
	template <class HandleSendType>
	static bool udpRequest(struct tRouteData<HandleSendType> *send){
		return cmdHandleBase::udpRequest(send);
	}

	// 本设备执行请求
	template <class HandleSendType,class HandleRecvType>
	static bool request(E_NetDevRunMode mode,struct tRouteData<HandleSendType> *send,struct tRouteData<HandleRecvType> *recv){
		bool ret = false;
        if(!send){
            qDebug("request send is NULL");
			return ret;
		}
        send->msg.sn = CControlTool::getDevSn();
        send->msg.sendMsgId = CControlTool::getOnlyId();
        send->msg.timestamp = QDateTime::currentSecsSinceEpoch();
		switch(mode){
			case NET_DEV_RUN_NULL:
                return ret;

            case NET_DEV_RUN_HTTP:
            {
                send->route.type = ROUTE_HTTP_CLIENT;
                if(send->route.httpClientInfo.url.empty())
                    ///////////////////// 需要添加网址 ////////////////////////////////
                    send->route.httpClientInfo.url = CNetConfig::getConfig().httpUrl + string("/") + send->msg.cmd;

                if(send->msg.appKey.empty())
                    send->msg.appKey = CNetConfig::getConfig().httpClientKey;

                send->msg.signature =CControlTool::getSignature(send->msg.sendMsgId+to_string(send->msg.timestamp));
                #ifdef  NET_MSG_LOG
                qDebug("net http send %s",send->toJsonString().c_str());
                #endif
                ret = controlManage::httpRequest(send, recv);
                #ifdef  NET_MSG_LOG
                if(ret && recv!= NULL){
                    qDebug("net http recv ret:%s",recv->toJsonString().c_str());
                }
                #endif
                return ret;
            }
			case NET_DEV_RUN_UDP:
			{
				send->route.type = ROUTE_UDP_CLIENT;
                if(send->msg.sendMsgId.empty()){
                    send->msg.sendMsgId = QUuid::createUuid().toString().toStdString();
				}
				if(send->msg.timestamp == 0){
                    send->msg.timestamp = QDateTime::currentSecsSinceEpoch();
				}
				if(send->msg.signature.empty()){
                    send->msg.signature = getSignature(send->msg.sendMsgId + to_string(send->msg.timestamp));
				}
				#ifdef  NET_MSG_LOG
                qDebug("net udp send %s",send->toJsonString().c_str());
				#endif
				ret = controlManage::udpRequest(send);
				return ret;
			}

		}
        qDebug("request  E_NetDevRunMode error:%d",mode);
		return ret;
	}

	// 字符串MD5方法
    static string strMd5(const string &str);

	// 获取IP
    static string getIp();

	// 获取设备MAC, 默认返回eth0mac， type 1 有线 2 无线
    static string getMac(int type);

	// 获取签名字符串
    static string getSignature(const string &body);

	// 获取设备sn
    static string getDevSn();

	// 查询图片格式
    static string findImageFormat(string &filePath);

public:
    // 初始化服务端
    static bool initServer(int32_t httpServerPort = 61028, int32_t udpPort = -1);
};

NETWORKSERVICE_END_NAMESPACE

#endif // CCONTRIL_MANAGE_H_
